package com.zdp.config.ribbon.nacos;

import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * @author sesshomaru
 * @date 2021/10/5 17:03
 * 自定义负载均衡策略
 * 基于nacos权重的负载
 * Ribbon为了方便拓展提供了AbstractLoadBalancerRule接口
 */
@Slf4j
public class NacosWeightedRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties nacosDiscoveryProperties;

    @Autowired
    private NacosServiceManager nacosServiceManager;

    @Override
    public Server choose(Object o) {
        try {
            BaseLoadBalancer loadBalancer = (BaseLoadBalancer) this.getLoadBalancer();
            log.info("lb={}", loadBalancer);
            // 想要请求微服务的名称
            String sever_name = loadBalancer.getName();
            // 实现基于权重的负载均衡算法(不过nacos有这种算法可以直接调用)
            // nacosDiscoveryProperties.namingServiceInstance()
            NamingService namingService = nacosServiceManager.getNamingService(nacosDiscoveryProperties.getNacosProperties());
            // nacos client自动通过基于权重的负载均衡算法，给我们选择一个健康的实例
            Instance instance = namingService.selectOneHealthyInstance(sever_name);
            log.info("选择的实例时 port={} instance={}", instance.getPort(), instance);
            // 把Instance转成nacos的Server
            return new NacosServer(instance);
        } catch (NacosException e) {
            return null;
        }
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
        // 读取配置文件，并初始化NacosWeightedRule,一般来说是留空的
    }

}
